import struct
import time
import sys
from scapy.all import *
from collections import deque
import platform
import numpy as np
import random

import config
import crc8

class HighSpeedFrameReceiver:
    def __init__(self, interface, max_data_size, expected_total_frames):
        self.interface = interface
        self.max_data_size = max_data_size
        self.expected_total_frames = expected_total_frames
        
        # payload模板数据
        self.expected_payload = bytes([i%255 for i in range(max_data_size-1-4)])
        
        # 初始化统计
        self.stats = self.Statistics(self.max_data_size, expected_total_frames)
        
        # 设置BPF过滤器（捕获所有以太网帧）
        self.bpf_filter = ""
        
        # 设置高性能捕获参数
        if platform.system() == "Linux":
            conf.use_pcap = False  # 在Linux上使用PF_PACKET
        else:
            conf.use_pcap = True  # 在BSD系统上使用libpcap
            
        conf.bufsize = 2**24  # 16MB接收缓冲区
        
        # 生成CRC8查找表
        self.crc8_table = crc8.make_crc8_table(poly=0x07)
        
        # 初始化序列号跟踪
        self.last_sequence_num = -1  # 上一个正确接收的序列号
        self.sequence_gap_count = 0  # 序列号不连续次数
        

        
    def mac_str_to_bytes(self, mac_str):
        """将MAC地址字符串转换为字节"""
        return bytes(int(x, 16) for x in mac_str.split(":"))
        
    class Statistics:
        def __init__(self, max_data_size, expected_total_frames):
            self.max_data_size = max_data_size
            self.expected_total_frames = expected_total_frames
            self.reset()
        
        def reset(self):
            self.start_time = time.perf_counter_ns()
            self.received_count = 0
            self.crc_error_count = 0
            self.sequence_error_count = 0  # 序列号错误计数
            self.avg_interval_ms = 0
            self.last_sequence_num = -1    # 记录上一个正确序列号
            self.total_bits = 0            # 累计接收比特数
            self.error_bits = 0            # 累计错误比特数
        
        def update(self, frame_length, 
                   crc_valid=True, 
                   sequence_valid=True, 
                   interval_ns=None,
                   bits_error=0,
                   bits_check=0):
            self.received_count += 1
            
            if not crc_valid:
                self.crc_error_count += 1
            
            if not sequence_valid:
                self.sequence_error_count += 1
                
            # 更新误比特率
            self.total_bits += bits_check
            self.error_bits += bits_error
                
            # 计算平均时间间隔
            if interval_ns is not None:
                interval_ms = interval_ns/1e6
                self.avg_interval_ms = (self.avg_interval_ms * (self.received_count - 1) + interval_ms) / self.received_count

        def get_stats(self):
            current_time = time.perf_counter_ns()
            elapsed_ns = current_time - self.start_time
            elapsed_sec = elapsed_ns / 1e9
            
            throughput = self.received_count / elapsed_sec if elapsed_sec > 0 else 0
            
            bit_err_rate = self.error_bits / self.total_bits if self.total_bits > 0 else 0
            
            # 计算丢包率（基于序列号）
            if self.last_sequence_num >= 0 and self.received_count > 0:
                expected_frames = self.last_sequence_num + 1  # 期望接收的帧数（从0开始）
                packet_loss = (self.crc_error_count) / expected_frames if expected_frames > 0 else 0
            else:
                packet_loss = 0
            
            return {
                "elapsed_time": elapsed_sec,
                "received_frames": self.received_count,
                "crc_error_frames": self.crc_error_count,
                "sequence_error_frames": self.sequence_error_count,
                "throughput": throughput,
                "avg_interval_ms": self.avg_interval_ms,
                "packet_loss_rate": packet_loss,
                "errors_bit": self.error_bits,
                "total_bits": self.total_bits,
                "bit_error_rate":bit_err_rate,
                "last_sequence_num": self.last_sequence_num,
            }
        
        def print_summary(self):
            stats = self.get_stats()
            print("\n" + "="*80)
            print("Statistics Summary")
            print("="*80)
            print(f"Elapsed Time: {stats['elapsed_time']:.2f} seconds")
            print(f"Expected Received Frames: {self.expected_total_frames}")
            print(f"Received Frames: {stats['received_frames']}")
            print(f"CRC Error Frames: {stats['crc_error_frames']}")
            print(f"Sequence Error Frames: {stats['sequence_error_frames']}")
            print(f"Packet Loss Rate: {stats['packet_loss_rate']:.5e}")
            print(f"Total Bits Checked: {stats['total_bits']}")
            print(f"Total Bit Errors: {stats['errors_bit']}")
            print(f"Bit Error Rate:{stats["bit_error_rate"]:.6e}")
            print(f"Throughput: {stats['throughput']:.2f} frames/sec")
            print(f"Average Interval: {stats['avg_interval_ms']:.3f} ms")
            print(f"Last Sequence Number: {stats['last_sequence_num']}")
            print("="*80)
    
    def _extract_sequence_number(self, frame_data):
        """从帧数据中提取序列号"""            
        # 提取序列号（大端序）(mac_header + ipv4_header)
        sequence_bytes = frame_data[34:38]
        try:
            sequence_num = struct.unpack(">I", sequence_bytes)[0]
            return sequence_num
        except:
            return None
    
    def _check_sequence_number(self, sequence_num):
        """
        检查序列号是否连续。
        """
        is_valid = True 
        if self.last_sequence_num == -1:
            if sequence_num == 0:
                is_valid = True
            else:
                is_valid = False
        else:
            expected_next = (self.last_sequence_num + 1) % (2**32)
            if sequence_num != expected_next:
                is_valid = False

        # 只要帧通过 CRC 校验，作为下一个帧的比较基准
        self.last_sequence_num = sequence_num
        self.stats.last_sequence_num = sequence_num 
        return is_valid
    
    def _calculate_ber(self,received_payload,payload_len):
        """计算误比特率"""
        error_bits = 0
        for a,b in zip(received_payload,self.expected_payload):
            error_bits += (a ^ b).bit_count()
        checked_bits = payload_len * 8;
        return error_bits,checked_bits
        
    def _process_frame(self, frame):
        """处理单个帧的回调函数"""
        try:            
            # 获取原始帧字节
            raw_frame = bytes(frame)
            
            # 提取以太网协议类型字段（第12-13字节）
            eth_type = raw_frame[12:14]
            eth_type_int = int.from_bytes(eth_type, byteorder='big')
                
            if eth_type_int != config.ETHERTYPE:
                return  # 如果不是目标协议则跳过
            
            # 检查帧长度是否合理
            if len(raw_frame) < config.TEST_MIN_DATA_SIZE:  # MAC头 + 序列号 + CRC
                return
            
            # 获取当前时间
            current_time = time.perf_counter_ns()
            # 计算当前时间间隔
            interval_ns = None
            if hasattr(self, 'last_receive_time') and self.last_receive_time is not None:
                interval_ns = current_time - self.last_receive_time

            self.last_receive_time = current_time
            
            # 提取序列号
            sequence_num = self._extract_sequence_number(raw_frame)
            if sequence_num is None:
                return
            
            # 计算CRC8（整个帧包括MAC头、序列号和随机数据，但不包括CRC8自身）
            frame_without_crc = raw_frame[:-1]
            calculated_crc = crc8.crc8(frame_without_crc, self.crc8_table)
            
            # 检查CRC8
            crc_valid = (calculated_crc == raw_frame[-1:])
            
            # 检查序列号连续性（仅对CRC有效的帧）
            sequence_valid = True
            if crc_valid:
                sequence_valid = self._check_sequence_number(sequence_num)
                
            # BER 统计
            error_bits = 0
            check_bits = 0
            received_payload = raw_frame[config.MAC_HEADER_LEN+config.IPv4_LEN+config.SEQ_NUM_LEN:-config.CRC_LEN];
            payload_len =  len(received_payload)
            error_bits,check_bits = self._calculate_ber(received_payload,payload_len)
            
            # 更新统计
            self.stats.update(len(raw_frame), 
                              crc_valid, 
                              sequence_valid, 
                              interval_ns,
                              error_bits,
                              check_bits)
            
            # 实时显示进度
            if self.stats.received_count % 100 == 0:
                stats = self.stats.get_stats()
                # sys.stdout.write(f"\rReceived: {stats['received_frames']} | "
                #                 f"CRC Errors: {stats['crc_error_frames']} | "
                #                 f"Seq Errors: {stats['sequence_error_frames']} | "
                #                 f"BER: {stats['bit_error_rate']:.6e} | "
                #                 f"Loss Rate: {stats['packet_loss_rate']:.4e}")
                # sys.stdout.flush()
                print(f"\rReceived: {stats['received_frames']} | "
                                 f"CRC Errors: {stats['crc_error_frames']} | "
                                 f"Seq Errors: {stats['sequence_error_frames']} | "
                                 f"BER: {stats['bit_error_rate']:.6e} | "
                                 f"Loss Rate: {stats['packet_loss_rate']:.4e}")
                    
        except Exception as e:
            print(f"\nError processing frame: {str(e)}")
    
    def run(self):
        """启动接收器"""
        print(f"Starting MAC frame receiver on {self.interface}")
        print(f"Max data size: {self.max_data_size} bytes")
        print(f"Expected total frames: {self.expected_total_frames}")
        print(f"Using BPF filter: {self.bpf_filter}")
        print("Press Ctrl+C to stop...")
        
        try:
            # 开始捕获
            sniff(iface=self.interface, 
                  prn=self._process_frame, 
                  store=0, 
                  filter=self.bpf_filter,
                  count=0,
                  timeout=None)

        except KeyboardInterrupt:
            print("\n\nReceiver stopped by user")
        except PermissionError:
            print("\nERROR: Permission denied. Did you run with sudo?")
        except Exception as e:
            print(f"\nERROR: {str(e)}")
            raise
        finally:
            self.stats.print_summary()
            
            
    def run_with_callback(self, callback, stop_flag=lambda: False):
        """启动接收器(GUI callback)"""
        print(f"Starting receiver on {self.interface}")
        try:
            def process(frame):
                self._process_frame(frame)
                if self.stats.received_count % 100 == 0:
                    callback(self.stats.get_stats())
            sniff(iface=self.interface, prn=process, store=0, filter=self.bpf_filter)
        except KeyboardInterrupt:
            print("Receiver stopped by user")
        finally:
            self.stats.print_summary()

# 使用示例
if __name__ == "__main__":
    # 创建并运行接收器
    receiver = HighSpeedFrameReceiver(
        interface=config.INTERFACE2,
        max_data_size=config.TEST_DATA_SIZE,  # 修改为最大数据大小
        expected_total_frames=config.TEST_TOTAL_FRAMES
    )
    
    receiver.run()